package com.sxds.wn.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import com.sxds.wn.IConstants;
import com.sxds.wn.security.SecurityService;
import com.sxds.wn.service.IService;
import com.sxds.wn.service.Request;
import com.sxds.wn.service.Response;

/**
 * Description: <p>Spring表单类型控制器基础类</p>
 * Content Desc:<p>Spring表单类型控制器基础类<p>
 * Copy Right of Personal Tangtao 2007-2020
 * @author Andy
 * @version 1.0 Create Date:@2008-11-12
 */
public abstract class BaseFormController extends SimpleFormController implements IConstants {

	//日志处理类
	protected Log log = LogFactory.getLog(getClass());
	//服务接口请求对象
	protected Request andyRequest;
	//服务接口返回对象
	protected Response andyResponse;
	//服务接口
	protected IService service;
	//安全认证授权服务接口
	protected SecurityService securityService;
	//取消
	protected String cancelView;
	
	public BaseFormController(){
		super();
	}

	@SuppressWarnings("unchecked")
	public void saveError(HttpServletRequest request, String error) {
		List errors = (List) request.getSession().getAttribute(PAGE_ERRORS_MESSAGES_KEY);
		if (errors == null) {
			errors = new ArrayList();
		}
		errors.add(error);
		request.getSession().setAttribute(PAGE_ERRORS_MESSAGES_KEY, errors);
	}
	
	public void saveError(HttpServletRequest request, SecurityException error) {
		List errors = (List) request.getSession().getAttribute(PAGE_ERRORS_MESSAGES_KEY);
		if (errors == null) {
			errors = new ArrayList();
		}
		errors.add(error);
		request.getSession().setAttribute(PAGE_ERRORS_MESSAGES_KEY, errors);
	}

	@SuppressWarnings("unchecked")
	public void saveMessage(HttpServletRequest request, String msg) {
		List messages = (List) request.getSession().getAttribute(PAGE_SUCCESS_MESSAGES_KEY);
		if (messages == null) {
			messages = new ArrayList();
		}
		messages.add(msg);
		request.getSession().setAttribute(PAGE_SUCCESS_MESSAGES_KEY, messages);
	}

	/**
	 * Convenience method for getting a i18n key's value.  Calling
	 * getMessageSourceAccessor() is used because the RequestContext variable
	 * is not set in unit tests b/c there's no DispatchServlet Request.
	 *
	 * @param msgKey
	 * @param locale the current locale
	 * @return
	 */
	public String getText(String msgKey, Locale locale) {
		return getMessageSourceAccessor().getMessage(msgKey, locale);
	}

	/**
	 * Convenient method for getting a i18n key's value with a single
	 * string argument.
	 *
	 * @param msgKey
	 * @param arg
	 * @param locale the current locale
	 * @return
	 */
	public String getText(String msgKey, String arg, Locale locale) {
		return getText(msgKey, new Object[] { arg }, locale);
	}

	/**
	 * Convenience method for getting a i18n key's value with arguments.
	 *
	 * @param msgKey
	 * @param args
	 * @param locale the current locale
	 * @return
	 */
	public String getText(String msgKey, Object[] args, Locale locale) {
		return getMessageSourceAccessor().getMessage(msgKey, args, locale);
	}

	/**
	 * Default behavior for FormControllers - redirect to the successView
	 * when the cancel button has been pressed.
	 */
	public ModelAndView processFormSubmission(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {
		if (request.getParameter("cancel") != null) {
			return new ModelAndView(getCancelView());
		}
		return super.processFormSubmission(request, response, command, errors);
	}

	/**
	 * Set up a custom property editor for converting form inputs to real objects
	 */
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) {
		binder.registerCustomEditor(Integer.class, null,
				new CustomNumberEditor(Integer.class, null, true));
		binder.registerCustomEditor(Long.class, null, new CustomNumberEditor(
				Long.class, null, true));
		binder.registerCustomEditor(byte[].class,
				new ByteArrayMultipartFileEditor());
		SimpleDateFormat dateFormat = new SimpleDateFormat(getText(
				"date.format", request.getLocale()));
		dateFormat.setLenient(false);
		binder.registerCustomEditor(Date.class, null, new CustomDateEditor(
				dateFormat, true));
	}

	/**
	 * 处理具体业务逻辑
	 * @param httpRequest javax.servlet.http.HttpServletRequest
	 * @param httpResponse javax.servlet.http.HttpServletResponse
	 * @return ModelAndView
	 * @throws Exception 异常
	 */
	public ModelAndView processService(HttpServletRequest httpRequest,
								  HttpServletResponse httpResponse) throws Exception {
		this.andyRequest = new Request(httpRequest);
		this.setRequestParamer();
		ModelAndView modelAndView = new ModelAndView(this.getSuccessView());
		try{
			this.andyResponse = service.process(this.andyRequest);
			Map pageAttributes = this.andyResponse.getPageAttributes();
			modelAndView.addObject((this.andyResponse.isOk()? "success":"failure"), true);
			if( !pageAttributes.isEmpty() ){
				Iterator it = pageAttributes.keySet().iterator();
				while( it.hasNext() ){
					String key = (String)it.next();
					Object value = pageAttributes.get(key);
					//httpRequest.setAttribute(key, value);
					modelAndView.addObject(key, value);
				}
			}
			if( this.andyResponse.isOk() ){
				//将讲结果保存在request对象中和ModelAndView
				this.processResponse();
			}else{
				this.saveError(httpRequest, andyResponse.getResponseMessage());
			}
		}catch(Exception ex){
			log.error("处理请求错误：",ex);
			this.saveError(httpRequest, "调用业务接口错误：" + ex.getMessage());
			httpRequest.setAttribute("exception", ex);
			throw new Exception("处理请求错误："+ex);
		}
		return modelAndView;
	}
	
	/**
	 * 子类可以定义覆盖此方法,设置调用的业务的请求参数
	 */
	protected abstract void setRequestParamer();
	
	/**
	 * 子类可以实现处理返回的结构，如把想要的对象写入到HttpServletRequest对象
	 */
	protected abstract void processResponse();
	
	/**
	 * Indicates what view to use when the cancel button has been pressed.
	 */
	public final void setCancelView(String cancelView) {
		this.cancelView = cancelView;
	}

	public final String getCancelView() {
		// Default to successView if cancelView is invalid
		if (this.cancelView == null || this.cancelView.length() == 0) {
			return getSuccessView();
		}
		return this.cancelView;
	}

	/**
	 * @param service the service to set
	 */
	public void setService(IService service) {
		this.service = service;
	}

	/**
	 * @param securityService the securityService to set
	 */
	public void setSecurityService(SecurityService securityService) {
		this.securityService = securityService;
	}
}
